/**@file main.c
 * @note 
 * @brief  测试代码
 * 
 * @author   luoxi
 * @date     20230106
 * @version  V1.0.0
 * 
 * @note Description here 
 * @note History:        
 * @note     <author>   <time>    <version >   <desc>
 * @note  
 * @warning  
 */
 
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <pthread.h>

#include "log_level.h"

#include "main.h"
#include "usercomm.h"




pthread_t  tids[3] = {0};

int pthreadSpawn(int pid_num, pthread_attr_t attr_AT, size_t nStacksize, void (*func)(), int priority);

static int check_coreprocess_is_running(void);
static int create_pidfile(void);

/**
 * @brief 主函数
 * 
 * @param[in] 1 参数个数 2 参数区分 
 * @return    0 ok
 */
int main(int argc, char **argv)
{
    int pid = getpid();
	log_custom("pid is %d", pid);

    int dwret = check_coreprocess_is_running();
    if(dwret)
    {
		log_error("have running ...");
	}
	else
	{
        dwret = create_pidfile();
	    if(OK != dwret)
	    {
   		    log_error("create file failed ...");
	    }
	}

    /* 起一个新的进程 */
    if((pid = vfork()) < 0) 
    {
      	log_error("can not fork, exit now");
    }
      
    if( pid == 0)
    {
		log_custom("vfork is success");
		exit(0);
    }

    pid = getpid();
	log_custom("pid is %d", pid);
   
	int ret = -1;
	pthread_attr_t attr_call;
	if((ret = pthreadSpawn(INIT_CALLBACK, attr_call, STACK_SIZE * 2, (void *)usercomm_thread_entry, START_FILE)) != OK)
	{
	    log_error("<main>: pthread_create read_file err, ret = %d", ret);
	}

	FOREVER
	{
	    usleep(100*1000);
	}
	return OK;
}

/**
 * @brief 创建线程
 * 
 * @param[in] 1 int pid_num 线程pid号
 * @param[in] 2 pthread_attr_t attr_AT 线程创建资源
 * @param[in] 3 size_t nStacksize 线程堆栈大小
 * @param[in] 4 void (*func)() 线程执行函数
 * @param[in] 5 int priority 线程优先级
 * @return    0 创建成功         -1 创建失败
 */
int pthreadSpawn(int pid_num, pthread_attr_t attr_AT, size_t nStacksize, void (*func)(),  int priority)
{
	int ret = -1;
	struct sched_param    params;

	if(NULL == func)
	{
	    log_error("args is error");
        return ERROR;
	}

	/* 启动线程 */
	//pthread_t MSG;
	//pthread_attr_t attr_AT;
	
	ret = pthread_attr_init(&attr_AT);  /* 初始化线程 */
	if (ret != OK)
	{
	    log_error("pthread_attr_init err, ret = %d", ret);
		pthread_attr_destroy(&attr_AT);
		return ret;
	}

	ret = pthread_attr_setschedpolicy(&attr_AT, SCHED_RR);/* 设置线程调度策略 SCHED_OTHER SCHED_FIFO SCHED_RR */
	if (ret != OK)
	{
	    log_error("pthread_attr_setschedpolicy err, ret = %d", ret);
		pthread_attr_destroy(&attr_AT);
		return ret;
	}
	
	ret = pthread_attr_setdetachstate (&attr_AT, PTHREAD_CREATE_DETACHED);/* 设置线程分离属性，防止内存泄露 */
	if (ret != OK)
	{
	    log_error("pthread_attr_setdetachstate err, ret = %d", ret);
		pthread_attr_destroy(&attr_AT);
		return ret;
	}

	ret = pthread_attr_getschedparam(&attr_AT, &params);    /* 得到线程优先级参数等 */
	if (ret != OK)
	{
	    log_error("pthread_attr_getschedparam err, ret = %d", ret);
		pthread_attr_destroy(&attr_AT);
		return ret;
	}
	
	params.sched_priority = priority;

	ret = pthread_attr_setschedparam(&attr_AT, &params);    /* 设置线程优先级参数 */
	if (ret != OK)
	{
	    log_error("pthread_attr_setschedparam err, ret = %d", ret);
		pthread_attr_destroy(&attr_AT);
		return ret;
	}
	
	ret = pthread_attr_setstacksize(&attr_AT, nStacksize);    /* 设置线程堆栈大小*/
	if (ret != OK)
	{
	    log_error("pthread_attr_setstacksize err, ret = %d", ret);
		pthread_attr_destroy(&attr_AT);
		return ret;
	}	

	if ((ret = pthread_create(&tids[pid_num], &attr_AT,(void *)func, NULL)) != OK)    /* 创建线程 */
	{
		log_error("pthread_create err, ret = %d", ret);
	}
	else
	{
		log_custom("create thread is succ!");

	}
    return ret;
}

/**
 * @brief 检查是否有同名线程在运行
 * 
 * @param[in]
 * @return    1 有同名线程正在运行         0 无同名线程正在运行
 */
static int check_coreprocess_is_running(void)
{
	int ret = 0;
	ret = access(PID_FILE, F_OK);
	if(0 == ret)
	{
		log_custom("have one process running");
		return TRUE;
	}
	else
	{
		return FALSE;
	}
}

/**
 * @brief 创建一个进程文件
 * 
 * @param[in]
 * @return    -1 失败         0 成功
 */
static int create_pidfile(void)
{
    int fd = 0;
    fd = open(PID_FILE, O_RDWR | O_CREAT | O_EXCL, 0);
    if (fd < 0)
    {
        log_error("file %s create failed", PID_FILE);
        return ERROR;
    }
    else
    {
        close(fd);
        return OK;
    }
}
